import os
import re
import time
import logging
from docx import Document
import PyPDF2
from PIL import Image
import pytesseract

from backend.app.config.settings import UPLOAD_DIR, AI_MODEL_CONFIG
from backend.app.utils.ai_utils import AIModelClient
from backend.app.database.models import Requirement, Activity
from backend.app.database.session import db_session

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def optimize_requirements(content: str, model_type=None) -> tuple:
    """优化需求文本

    使用AI模型优化需求文本
    返回: (优化后的内容, 处理时间)
    """
    start_time = time.time()

    # 创建AI客户端
    ai_client = AIModelClient.get_client(model_type)
    model_used = model_type or AI_MODEL_CONFIG.get("default_model", "douban")

    # 构建提示词
    prompt = f"""
    请作为一位经验丰富且专业的需求分析专家，对以下提供的软件需求文档进行全面且细致的优化。在优化过程中，请务必严格遵循以下详细原则：

    ### 需求完整性与清晰度
    1. **内容无遗漏**：对原需求文档中的所有功能点和业务流程进行完整梳理，确保没有任何重要信息被遗漏。若发现原文档中存在信息缺失的情况，应根据上下文和行业经验合理补充必要的细节。
    2. **表述清晰准确**：使用简洁明了、无歧义的语言来描述需求。避免使用模糊、笼统或容易引起误解的词汇和语句。对于复杂的功能或业务规则，应进行详细解释和说明，确保需求能够被开发团队和测试团队准确理解。
    3. **逻辑连贯一致**：确保需求文档中的各个部分之间逻辑连贯，不存在矛盾或冲突的地方。功能点之间的依赖关系、业务流程的先后顺序等都应清晰明确。

    ### 非功能性需求添加
    1. **性能需求**：根据系统的预期使用场景和用户数量，确定合理的性能指标，如响应时间、吞吐量、并发用户数等。例如，对于关键业务操作，系统的响应时间应控制在 3 秒以内；系统应能够支持至少 1000 个并发用户同时在线操作。
    2. **安全性需求**：考虑系统在数据安全、访问控制、身份认证等方面的需求。例如，用户密码应进行加密存储；系统应提供不同级别的用户权限管理，确保只有授权用户才能访问敏感数据和执行特定操作。
    3. **可维护性需求**：提出便于系统维护和升级的要求，如代码的可读性、可扩展性、模块化设计等。例如，代码应遵循统一的编码规范，采用模块化设计，每个模块应具有明确的功能和接口。
    4. **兼容性需求**：明确系统在不同操作系统、浏览器、设备等环境下的兼容性要求。例如，系统应支持在 Windows 10、Mac OS X 10.15 及以上版本的操作系统上正常运行；在 Chrome、Firefox、Safari 等主流浏览器中显示正常且功能可用。
    5. **可用性需求**：确定系统的可用性目标，如系统的停机时间、故障恢复时间等。例如，系统的可用性应达到 99.9%以上，即每年的停机时间不超过 8.76 小时；在发生故障时，系统应能够在 30 分钟内恢复正常运行。

    ### Markdown 格式使用
    1. **标题分级**：使用不同级别的标题来组织需求文档的结构，使文档层次分明。例如，使用一级标题 `#` 表示主要功能模块，二级标题 `##` 表示子功能或业务流程，三级标题 `###` 表示具体的需求点。
    2. **列表使用**：对于并列的需求点或步骤，应使用列表进行整理。有序列表 `1.` 用于表示有先后顺序的步骤，无序列表 `-` 用于表示并列的需求点。
    3. **代码块与引用**：对于代码示例、配置信息等内容，应使用代码块 ````language python ```` 进行展示；对于引用的外部文档或资料，应使用引用格式 `> 引用内容`。

    ### 功能模块分类整理
    1. **合理划分模块**：根据系统的业务功能和逻辑关系，将需求划分为不同的功能模块。每个模块应具有相对独立的功能和职责，模块之间的接口和交互应清晰明确。
    2. **模块描述详细**：对每个功能模块进行详细的描述，包括模块的功能概述、输入输出、业务流程等。例如，对于用户管理模块，应描述该模块的主要功能是管理用户的注册、登录、信息修改等操作；输入为用户提交的表单数据，输出为操作结果信息；业务流程包括用户输入信息、系统验证信息、更新数据库等步骤。

    ### 需求可测试性与可实现性
    1. **可测试性**：确保每个需求点都具有明确的测试条件和预期结果，便于测试团队进行测试。例如，对于一个搜索功能的需求，应明确规定输入不同的关键词时，系统应返回的搜索结果范围和格式。
    2. **可实现性**：需求应符合当前的技术水平和资源限制，是开发团队能够实际实现的。在提出需求时，应考虑到技术可行性、成本效益等因素。

    需求文档内容：
    {content}

    请输出优化后的需求文档，严格按照上述原则进行编写，确保文档结构清晰、易懂、质量高且无逻辑错误。
    """

    # 调用AI模型
    try:
        optimized = ai_client.generate(prompt)
        processing_time = time.time() - start_time
        logger.info(f"需求优化完成，耗时: {processing_time:.2f}秒，使用模型: {model_used}")
        return optimized, processing_time, model_used
    except Exception as e:
        logger.error(f"优化需求失败，使用模型 {model_used}: {str(e)}")
        # 如果AI调用失败，使用备用方法
        optimized = fallback_optimize_requirements(content)
        processing_time = time.time() - start_time
        return optimized, processing_time, "fallback"

def fallback_optimize_requirements(content: str) -> str:
    """备用的需求优化方法，当AI调用失败时使用"""
    # 示例优化逻辑
    if "用户登录" in content:
        return """## 用户登录功能需求

1. **基本登录流程**
   - 用户应能通过用户名和密码组合进行系统登录
   - 系统应验证用户提供的凭据是否匹配数据库中的记录
   - 登录成功后应重定向到用户主页或上次访问页面

2. **错误处理**
   - 当用户名不存在时，显示"用户名不存在"的错误提示
   - 当密码错误时，显示"密码错误"的错误提示
   - 错误信息应清晰可见，位于登录表单附近
   - 错误发生时不应清空用户名字段，但应清空密码字段

3. **安全考虑**
   - 密码在传输和存储过程中必须加密
   - 实施防暴力破解措施，如连续5次密码错误后锁定账户30分钟
   - 登录页面应实现CSRF保护

4. **用户体验**
   - 提供"记住我"功能，允许用户在特定设备上保持登录状态
   - 提供"忘记密码"链接，允许用户重置密码
   - 登录过程中应显示适当的加载指示器"""
    else:
        # 通用优化逻辑
        lines = content.strip().split('\n')
        title = lines[0] if lines else "需求"

        optimized = f"## {title}\n\n"

        # 提取需求点并格式化
        requirements = []
        for line in lines[1:]:
            line = line.strip()
            if line:
                if re.match(r'^\d+\.', line):
                    # 已经是编号格式的需求点
                    requirements.append(line)
                else:
                    # 添加为新的需求点
                    requirements.append(f"{len(requirements) + 1}. {line}")

        # 分类整理需求点
        if requirements:
            optimized += "1. **基本功能**\n"
            for req in requirements:
                optimized += f"   - {req.split('.', 1)[1].strip()}\n"

            optimized += "\n2. **非功能需求**\n"
            optimized += "   - 系统应具有良好的性能和响应速度\n"
            optimized += "   - 界面应简洁直观，易于使用\n"
            optimized += "   - 应提供适当的错误处理和用户反馈\n"

        return optimized

def extract_text_from_file(file_path: str, file_name: str) -> str:
    """从不同类型的文件中提取文本"""
    file_ext = os.path.splitext(file_name)[1].lower()

    try:
        if file_ext in ['.docx', '.doc']:
            # 处理Word文档
            doc = Document(file_path)
            return '\n'.join([para.text for para in doc.paragraphs])

        elif file_ext == '.pdf':
            # 处理PDF文件
            text = ""
            with open(file_path, 'rb') as file:
                reader = PyPDF2.PdfReader(file)
                for page in reader.pages:
                    text += page.extract_text() + "\n"
            return text

        elif file_ext in ['.jpg', '.jpeg', '.png']:
            # 处理图片文件（OCR）
            image = Image.open(file_path)
            return pytesseract.image_to_string(image, lang='chi_sim+eng')

        else:
            # 处理纯文本文件
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as file:
                return file.read()
    except Exception as e:
        logger.error(f"提取文件内容失败 {file_path}: {str(e)}")
        return f"无法提取文件内容: {str(e)}"

def optimize_requirements_from_file(file_path: str, file_name: str, model_type=None) -> tuple:
    """从文件中提取并优化需求"""
    # 提取文本
    extracted_text = extract_text_from_file(file_path, file_name)

    # 优化需求，添加 model_type 参数
    optimized, processing_time, model_used = optimize_requirements(extracted_text, model_type)

    return extracted_text, optimized, processing_time, model_used

def save_requirement(title, original_content, optimized_content, user_id, processing_time, model_used):
    """保存需求到数据库"""
    try:
        with db_session() as session:
            # 创建需求记录
            requirement = Requirement(
                title=title,
                original_content=original_content,
                optimized_content=optimized_content,
                user_id=user_id,
                processing_time=processing_time,
                model_used=model_used
            )
            session.add(requirement)

            # 记录活动
            activity = Activity(
                user_id=user_id,
                activity_type="requirement_optimization",
                description=f"优化了{title}需求"
            )
            session.add(activity)

            session.commit()
            requirement_id = requirement.id
            logger.info(f"需求 {title} 已成功保存到数据库，ID: {requirement_id}")
            return requirement_id
    except Exception as e:
        logger.error(f"保存需求到数据库失败: {str(e)}")
        raise